package com.it.flowable.util;

import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class PrintModelUtils {
    public static String modelToXml(BpmnModel bpmnModel) {
        // 转换为XML
        BpmnXMLConverter converter = new BpmnXMLConverter();
        byte[] xmlBytes = converter.convertToXML(bpmnModel);

        return new String(xmlBytes, StandardCharsets.UTF_8);
    }
    /**
     * 生成BPMN文件
     */
    public static void generateBpmnFile(BpmnModel model, String filename) {
        // new BpmnAutoLayout(model).execute();

        Path path = Paths.get(filename + ".bpmn20.xml");
        try {
            Files.write(path, new BpmnXMLConverter().convertToXML(model));
            System.out.println("BPMN文件已生成: " + path.toAbsolutePath());
        } catch (IOException e) {
            throw new RuntimeException("写入BPMN文件失败", e);
        }
    }

    public static String serviceTaskToXml(ServiceTask serviceTask) {
        try {
            // 创建一个简单的BPMN流程包含该ServiceTask
            BpmnModel bpmnModel = new BpmnModel();
            Process process = new Process();
            process.setId("testProcess");

            // 添加ServiceTask到流程
            process.addFlowElement(serviceTask);

            // 添加开始和结束事件以形成完整流程
            StartEvent startEvent = new StartEvent();
            startEvent.setId("startEvent");
            process.addFlowElement(startEvent);

            EndEvent endEvent = new EndEvent();
            endEvent.setId("endEvent");
            process.addFlowElement(endEvent);

            // 添加序列流
            SequenceFlow flow1 = new SequenceFlow("startEvent", serviceTask.getId());
            SequenceFlow flow2 = new SequenceFlow(serviceTask.getId(), "endEvent");
            process.addFlowElement(flow1);
            process.addFlowElement(flow2);

            bpmnModel.addProcess(process);

            // 转换为XML
            BpmnXMLConverter converter = new BpmnXMLConverter();
            byte[] xmlBytes = converter.convertToXML(bpmnModel);

            return new String(xmlBytes, StandardCharsets.UTF_8);

        } catch (Exception e) {
            throw new RuntimeException("转换失败", e);
        }
    }


    /**
     * 生成详细的ServiceTask XML
     */
    public static String generateDetailedServiceTaskXml(ServiceTask serviceTask) {
        StringBuilder xml = new StringBuilder();

        xml.append("<!-- ServiceTask详细信息 -->\n");
        xml.append("<serviceTask\n");
        xml.append("  id=\"").append(serviceTask.getId()).append("\"\n");
        xml.append("  name=\"").append(escapeXml(serviceTask.getName())).append("\"\n");

        // 添加所有可能的基础属性
        addAttribute(xml, "implementation", serviceTask.getImplementation());
        addAttribute(xml, "implementationType", serviceTask.getImplementationType());
        addAttribute(xml, "resultVariable", serviceTask.getResultVariableName());
        addAttribute(xml, "async", String.valueOf(serviceTask.isAsynchronous()));
        addAttribute(xml, "exclusive", String.valueOf(serviceTask.isNotExclusive()));
        // addAttribute(xml, "triggerable", serviceTask.getTriggerable());

        // 添加特定类型的属性
        if ("class".equals(serviceTask.getImplementationType())) {
            addAttribute(xml, "class", serviceTask.getImplementation());
        } else if ("expression".equals(serviceTask.getImplementationType())) {
            addAttribute(xml, "expression", serviceTask.getImplementation());
        } else if ("delegateExpression".equals(serviceTask.getImplementationType())) {
            addAttribute(xml, "delegateExpression", serviceTask.getImplementation());
        }

        xml.append(">\n");

        // 处理字段扩展
        if (!serviceTask.getFieldExtensions().isEmpty()) {
            xml.append("  <extensionElements>\n");
            for (FieldExtension field : serviceTask.getFieldExtensions()) {
                xml.append("    <flowable:field name=\"").append(field.getFieldName()).append("\">\n");
                if (field.getStringValue() != null) {
                    xml.append("      <flowable:string>")
                            .append(escapeXml(field.getStringValue()))
                            .append("</flowable:string>\n");
                } else if (field.getExpression() != null) {
                    xml.append("      <flowable:expression>")
                            .append(escapeXml(field.getExpression()))
                            .append("</flowable:expression>\n");
                }
                xml.append("    </flowable:field>\n");
            }
            xml.append("  </extensionElements>\n");
        }

        xml.append("</serviceTask>");

        return xml.toString();
    }

    private static void addAttribute(StringBuilder xml, String attrName, String attrValue) {
        if (attrValue != null && !attrValue.trim().isEmpty()) {
            xml.append("  flowable:").append(attrName).append("=\"")
                    .append(escapeXml(attrValue)).append("\"\n");
        }
    }

    private static String escapeXml(String text) {
        if (text == null) return "";
        return text.replace("&", "&amp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;")
                .replace("\"", "&quot;")
                .replace("'", "&apos;");
    }

    static void modelToFile(BpmnModel model, String file) {
        Path path = Paths.get(file);
        try {
            Files.write(path, new BpmnXMLConverter().convertToXML(model));
        } catch (IOException e) {
            throw new RuntimeException("写入BPMN文件失败", e);
        }
    }
}
